/*
 * Unidata Platform Community Edition
 * Copyright (c) 2013-2020, UNIDATA LLC, All rights reserved.
 * This file is part of the Unidata Platform Community Edition software.
 *
 * Unidata Platform Community Edition is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Unidata Platform Community Edition is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

package org.unidata.mdm.data.service;

import java.time.LocalDateTime;
import java.util.List;

import org.unidata.mdm.core.type.timeline.Timeline;
import org.unidata.mdm.data.context.DeleteRequestContext;
import org.unidata.mdm.data.context.GetMultipleRequestContext;
import org.unidata.mdm.data.context.GetRecordTimelineRequestContext;
import org.unidata.mdm.data.context.GetRequestContext;
import org.unidata.mdm.data.context.JoinRequestContext;
import org.unidata.mdm.data.context.MergeRequestContext;
import org.unidata.mdm.data.context.PreviewRequestContext;
import org.unidata.mdm.data.context.RecordIdentityContext;
import org.unidata.mdm.data.context.RestoreRecordRequestContext;
import org.unidata.mdm.data.context.SplitRecordRequestContext;
import org.unidata.mdm.data.context.UpsertRequestContext;
import org.unidata.mdm.data.dto.DeleteRecordDTO;
import org.unidata.mdm.data.dto.GetRecordDTO;
import org.unidata.mdm.data.dto.GetRecordsDTO;
import org.unidata.mdm.data.dto.KeysJoinDTO;
import org.unidata.mdm.data.dto.MergeRecordsDTO;
import org.unidata.mdm.data.dto.RecordsBulkResultDTO;
import org.unidata.mdm.data.dto.RestoreRecordDTO;
import org.unidata.mdm.data.dto.SplitRecordsDTO;
import org.unidata.mdm.data.dto.UpsertRecordDTO;
import org.unidata.mdm.data.type.apply.batch.impl.RecordDeleteBatchSetAccumulator;
import org.unidata.mdm.data.type.apply.batch.impl.RecordMergeBatchSetAccumulator;
import org.unidata.mdm.data.type.apply.batch.impl.RecordRestoreBatchSetAccumulator;
import org.unidata.mdm.data.type.apply.batch.impl.RecordUpsertBatchSetAccumulator;
import org.unidata.mdm.data.type.data.OriginRecord;
import org.unidata.mdm.data.type.keys.RecordKeys;

public interface DataRecordsService {
    /**
     * Gets a records using parameters set by the context.
     * @param ctx the request context
     * @return {@link GetRecordDTO}
     */
    GetRecordDTO getRecord(GetRequestContext ctx);
    /**
     * Gets keys for identity context.
     * @param ctx the context
     * @return keys or null
     */
    RecordKeys identify(RecordIdentityContext ctx);
    /**
     * Joins a new external id to an existing etalon key.
     * @param ctx the context
     * @return result
     */
    KeysJoinDTO join(JoinRequestContext ctx);
    /**
     * Gets an etalon record using parameters set by the context.
     * @param ctx the request context
     * @return {@link GetRecordDTO}
     */
    GetRecordDTO preview(PreviewRequestContext ctx);
    /**
     * Gets a records list using parameters set by the context.
     * @param ctx the request context
     * @return {@link GetRecordsDTO}
     */
    GetRecordsDTO getRecords(GetMultipleRequestContext ctx);
    /**
     * Deletes a record.
     *
     * @param ctx the context
     * @return key of the record deleted
     */
    DeleteRecordDTO deleteRecord(DeleteRequestContext ctx);
    /**
     * Merges several etalon records (and their origins) to one winner record.
     *
     * @param ctx current merge context
     * @return merged digest
     */
    MergeRecordsDTO merge(MergeRequestContext ctx);
    /**
     * Loads record timeline.
     * @param ctx the request
     * @return timeline
     */
    Timeline<OriginRecord> loadTimeline(GetRecordTimelineRequestContext ctx);
    /**
     * @param ctx - record upsert context
     * @return {@link UpsertRecordDTO}
     */
    UpsertRecordDTO upsertRecord(UpsertRequestContext ctx);
    /**
     * Copy record with save in 'draft' state
     * @param ctx context for get source record
     * @return upsert result by periods
     */
    List<UpsertRecordDTO> copyRecord(GetRequestContext ctx);
    /**
     * Publish record and all periods from 'draft' state to 'publish'
     * @param ctx context for get record
     * @return upsert result by periods
     */
    List<UpsertRecordDTO> applyDraftRecord(GetRequestContext ctx);
    /**
     * Restore period or a whole record.
     * @param ctx the context
     * @return result
     */
    RestoreRecordDTO restore(RestoreRecordRequestContext ctx);
    /**
     * Detach origin from current etalon to new created etalon.
     *
     * @return new etalon id, to which detach origin
     */
    SplitRecordsDTO detachOrigin(SplitRecordRequestContext ctx);
    /**
     * Reindex record by etalon id
     * @param ctx ctx for identify
     * @return
     */
    boolean reindexEtalon(final RecordIdentityContext ctx);
    /**
     * Does mostly the same thing as the method above, but applies DQ rules additionally.
     * @param ctx the context to process
     */
    void reapplyEtalon(UpsertRequestContext ctx);

    List<String> selectCovered(List<String> etalonIds, LocalDateTime from, LocalDateTime to, boolean full);
    /**
     * Get a record as XML using parameters set by the context.
     * @param ctx the request context
     * @return {@link GetRecordDTO}
     */
    String getRecordAsXMLString(GetRequestContext ctx);
    /**
     * Does bulk upsert via collection of contexts.
     * @param ctxs - collection of upsert record contexts.
     * @return bulk result  {@link RecordsBulkResultDTO}
     */
    RecordsBulkResultDTO batchUpsertRecords(List<UpsertRequestContext> ctxs);
    /**
     * Does bulk upsert via collection of contexts.
     * @param ctxs - collection of upsert record contexts.
     * @param abortOnFailure abort on first failure
     * @return bulk result {@link RecordsBulkResultDTO}
     */
    RecordsBulkResultDTO batchUpsertRecords(List<UpsertRequestContext> ctxs, boolean abortOnFailure);
    /**
     * Does bulk upsert via accumulator.
     * @param accumulator the accumulator
     * @return bulk result
     */
    RecordsBulkResultDTO batchUpsertRecords(RecordUpsertBatchSetAccumulator accumulator);
    /**
     * Does bulk delete via temporary accumulator.
     * @param ctxs - collection of delete record contexts.
     * @return bulk result {@link RecordsBulkResultDTO}
     */
    RecordsBulkResultDTO batchDeleteRecords(List<DeleteRequestContext> ctxs);
    /**
     * Does bulk delete via temporary accumulator.
     * @param ctxs - collection of delete record contexts.
     * @param abortOnFailure abort on first failure
     * @return bulk result {@link RecordsBulkResultDTO}
     */
    RecordsBulkResultDTO batchDeleteRecords(List<DeleteRequestContext> ctxs, boolean abortOnFailure);
    /**
     * Does bulk delete via accumulator.
     * @param accumulator the accumulator
     * @return bulk result
     */
    RecordsBulkResultDTO batchDeleteRecords(RecordDeleteBatchSetAccumulator accumulator);
    /**
     * Does bulk merge via temporary accumulator.
     * @param ctxs - collection of merge record contexts.
     * @return bulk result {@link RecordsBulkResultDTO}
     */
    RecordsBulkResultDTO batchMergeRecords(List<MergeRequestContext> ctxs);
    /**
     * Does bulk merge via temporary accumulator.
     * @param ctxs - collection of merge record contexts.
     * @param abortOnFailure abort on first failure
     * @return bulk result {@link RecordsBulkResultDTO}
     */
    RecordsBulkResultDTO batchMergeRecords(List<MergeRequestContext> ctxs, boolean abortOnFailure);
    /**
     * Does bulk merge via accumulator.
     * @param accumulator the accumulator
     * @return bulk result
     */
    RecordsBulkResultDTO batchMergeRecords(RecordMergeBatchSetAccumulator accumulator);
    /**
     * Does bulk restore via temporary accumulator.
     * @param ctxs - collection of restore record/period contexts.
     * @return bulk result {@link RecordsBulkResultDTO}
     */
    RecordsBulkResultDTO batchRestoreRecords(List<RestoreRecordRequestContext> ctxs);
    /**
     * Does bulk restore via temporary accumulator.
     * @param ctxs - collection of restore record/period contexts.
     * @param abortOnFailure abort on first failure
     * @return bulk result {@link RecordsBulkResultDTO}
     */
    RecordsBulkResultDTO batchRestoreRecords(List<RestoreRecordRequestContext> ctxs, boolean abortOnFailure);
    /**
     * Does bulk restore via accumulator.
     * @param accumulator the accumulator
     * @return bulk result
     */
    RecordsBulkResultDTO batchRestoreRecords(RecordRestoreBatchSetAccumulator accumulator);
}
